<template>
  <div>
    <a-alert type="warning" show-icon style="margin-bottom: 18px">
      <template #description>
        用于异常、留痕等日志记录，快速拥有一个日志管理平台。
        <a
          href="https://doc.21ds.cn/detail?doc=4731341806141859/4840069379677989"
          target="_blank"
          rel="noopener noreferrer"
          >对接文档</a
        >
      </template>
    </a-alert>
    <div class="table-page-search-wrapper">
      <a-row type="flex" justify="space-between" align="middle">
        <a-col :span="16">
          <a-form layout="inline" :model="listQuery">
            <a-form-item label="搜索项">
              <a-input v-model:value="listQuery.title" placeholder="输入名称/ID搜索..." allowClear />
            </a-form-item>
            <a-form-item>
              <a-button type="primary" @click="searchSubmit"> 搜索 </a-button>
            </a-form-item>
            <a-form-item>
              <a-button
                v-permission="{ action: 'del_log_site_batch' }"
                type="primary"
                danger
                :disabled="selectedRowKeys.length === 0"
                @click="deleteSelect"
              >
                <template #icon>
                  <DeleteOutlined />
                </template>
                删除所选
              </a-button>
            </a-form-item>
          </a-form>
        </a-col>
        <a-col :span="8">
          <div style="margin-right: 0px; float: right; display: flex; align-item: center">
            <a-tooltip placement="top">
              <template #title>
                <span>刷新列表</span>
              </template>
              <a-button @click="reloadList">
                <template #icon><SyncOutlined /></template>
              </a-button>
            </a-tooltip>
            <a-button
              v-permission="{ action: 'log_site_add' }"
              type="primary"
              style="margin-left: 12px"
              @click="log_site_add"
            >
              <template #icon><PlusOutlined /></template> 新增站点
            </a-button>
          </div>
        </a-col>
      </a-row>
    </div>
    <a-table
      :columns="columns"
      :rowKey="(record) => record._id"
      :dataSource="dataList.data"
      :loading="loading"
      :pagination="pagination"
      :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
      @change="handleTableChange"
    >
      <template #status="{ text: record }">
        <a-tag v-if="record == 1" color="green">启用</a-tag>
        <a-tag v-if="record == 0" color="red">不启用</a-tag>
      </template>
      <template #notice_open="{ text: record }">
        <a-tag v-if="record == 1" color="blue">发送</a-tag>
        <a-tag v-if="record == 0">不发送</a-tag>
      </template>
      <template #list_title="{ text: record }">
        <a-tooltip placement="top">
          <template #title>
            <span>查看站点日志</span>
          </template>
          <router-link :to="{ name: 'ExceptionLog', query: { site_id: record?._id || '' } }">
            <UnorderedListOutlined /> {{ record?.title }}
          </router-link>
        </a-tooltip>
      </template>
      <template #action="{ text: record }">
        <a v-permission="{ action: 'log_site_add' }" @click="log_site_edit(record)"
          ><EditOutlined /> 编辑</a
        >
        <a-divider v-permission="{ action: 'log_site_copy' }" type="vertical" />
        <a v-permission="{ action: 'log_site_copy' }" @click="log_site_copy(record)"
          ><CopyOutlined /> 复制</a
        >
        <a-divider v-permission="{ action: 'del_log_site_batch' }" type="vertical" />
        <a
          v-permission="{ action: 'del_log_site_batch' }"
          style="color: red"
          @click="log_site_delete(record)"
          ><DeleteOutlined /> 删除</a
        >
      </template>
    </a-table>
    <a-drawer
      width="45%"
      title="站点详情"
      placement="right"
      :open="drawerShow"
      @close="
        () => {
          drawerShow = false
        }
      "
    >
      <template #extra>
        <a-button
          style="margin-right: 8px"
          @click="
            () => {
              drawerShow = false
            }
          "
          >取消</a-button
        >
        <a-button type="primary" :loading="submitLoading" @click="addItem">提交</a-button>
      </template>
      <a-form
        ref="formRef"
        :model="FormState"
        :rules="FormRule"
        :labelCol="labelCol"
        :wrapperCol="wrapperCol"
      >
        <a-form-item label="站点名称" has-feedback required name="title">
          <a-input v-model:value="FormState.title" placeholder="请输入站点名称" />
        </a-form-item>
        <a-form-item label="通知标题预览">
          【新日志提醒】- {{ FormState.title || '站点名称' }}
        </a-form-item>
        <a-form-item label="日志存储" has-feedback required name="save_day">
          <a-tooltip placement="top">
            <template #title>
              <span>请输入日志保留天数，仅限数字，单位：天</span>
            </template>
            <a-input
              v-model:value="FormState.save_day"
              placeholder="请输入日志保留天数，仅限数字"
              suffix="天"
            />
          </a-tooltip>
        </a-form-item>
        <a-form-item label="日志参数" has-feedback required name="log_params">
          <a-tooltip placement="top">
            <template #title>
              <span
                >请输入日志参数，格式：字段名称|字段名|列表显示(1=显示，0=不显示)|列表宽度(如:200px，则输入200即可)，一行一个，如：所属文件|file|1|200。
                系统保留参数：_id,uid,username,create_time,remote_ip_area</span
              >
            </template>
            <a-textarea
              v-model:value="FormState.log_params"
              show-count
              placeholder="请输入日志参数，格式：字段名称|字段名|列表显示(1=显示，0=不显示)，一行一个，如：所属文件|file|1。 系统保留参数：_id,uid,username,create_time,remote_ip_area"
              :rows="10"
            />
          </a-tooltip>
        </a-form-item>
        <a-form-item label="支持搜索参数" has-feedback required name="search_params">
          <a-tooltip placement="top">
            <template #title>
              <span
                >请输入支持搜索的参数，多个参数之间以|分隔，如：file|trace|url，不支持的系统保留参数有：_id,uid,username,create_time,remote_ip_area</span
              >
            </template>
            <a-select
              v-model:value="FormState.search_params"
              mode="tags"
              style="width: 100%"
              :token-separators="['|']"
              placeholder="多个参数之间以|分隔"
              :options="optionsParams"
            />
          </a-tooltip>
        </a-form-item>
        <a-form-item label="SecretKey" name="server_secret">
          <a-input-search
            v-model:value="FormState.server_secret"
            placeholder="点击右侧“获取密钥”按钮进行获取"
            enter-button="获取密钥"
            @search="resetSecret"
          />
        </a-form-item>
        <a-form-item label="是否发送通知" has-feedback required name="notice_open">
          <a-radio-group v-model:value="FormState.notice_open" name="notice_open">
            <a-radio :key="1" :value="1">发送</a-radio>
            <a-radio :key="0" :value="0">不发送</a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item
          v-if="FormState.notice_open == 1"
          label="监控通知"
          has-feedback
          required
          name="ps_id"
        >
          <a-select v-model:value="FormState.ps_id" placeholder="请选择通知推送配置">
            <a-select-option v-for="d in allPush" :key="d._id" :value="d._id">
              {{ d.title }}
            </a-select-option>
            <template #notFoundContent>
              <a-empty
                image="https://img.alicdn.com/imgextra/i3/573804794/O1CN01IO097G1lHhdtoisyG_!!573804794.png"
                :image-style="{
                  height: '90px'
                }"
              >
                <template #description>
                  <view style="color: rgba(0, 0, 0, 0.88); padding-top: 20px">
                    暂无可选项，请先
                    <router-link :to="{ name: 'pushServer' }" target="_blank">添加</router-link>
                  </view>
                </template>
              </a-empty>
            </template>
          </a-select>
        </a-form-item>
        <a-form-item
          v-if="FormState.notice_open == 1"
          label="通知中包含参数"
          has-feedback
          required
          name="notice_params"
        >
          <a-tooltip placement="top">
            <template #title>
              <span
                >请输入通知中包含参数，多个参数之间以|分隔，如：file|trace|url，不支持的系统保留参数有：_id,uid,username,create_time</span
              >
            </template>
            <a-select
              v-model:value="FormState.notice_params"
              mode="tags"
              style="width: 100%"
              :token-separators="['|']"
              placeholder="多个参数之间以|分隔"
              :options="optionsParams"
            />
          </a-tooltip>
        </a-form-item>
        <a-form-item
          v-if="FormState.notice_open == 1"
          label="参数中含有时不通知"
          name="notice_params_ignore"
        >
          <a-tooltip placement="top">
            <template #title>
              <span
                >参数内容中包含指定内容时忽略通知，多个参数时以换行分隔，多个参数之间为“或”关系，实例：message=module
                not exists(解释说明：message参数值中包含module not exists时不触发通知)</span
              >
            </template>
            <a-textarea
              v-model:value="FormState.notice_params_ignore"
              show-count
              placeholder="(可选) 如：message=module not exists，多个参数以换行分隔"
              :rows="2"
            />
          </a-tooltip>
        </a-form-item>
        <a-form-item label="标签页预览参数聚合" name="browser_label_params">
          <a-tooltip placement="top">
            <template #title>
              <span
                >如果需要在标签页预览日志内容时同时展示其他字段的内容，可设置本参数，多个需要聚合展示的参数以换行分隔，同一参数聚合多个参数的以|分隔，如：trace=file|trace|url，不支持的系统保留参数有：_id,uid,username,create_time
                (注：本参数在[日志详情]-[在新标签页显示]起效)</span
              >
            </template>
            <a-textarea
              v-model:value="FormState.browser_label_params"
              show-count
              placeholder="(可选) 如：trace=file|trace|url，多个参数以换行分隔"
              :rows="2"
            />
          </a-tooltip>
        </a-form-item>
        <a-form-item label="状态" has-feedback required name="status">
          <a-radio-group v-model:value="FormState.status" name="status">
            <a-radio :key="1" :value="1">启用</a-radio>
            <a-radio :key="0" :value="0">不启用</a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item label="备注" name="desc">
          <a-textarea v-model:value="FormState.desc" show-count placeholder="(可选)" :rows="2" />
        </a-form-item>
      </a-form>
    </a-drawer>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs, onMounted, ref, toRaw, watch } from 'vue'
import {
  Row,
  Col,
  Modal,
  Divider,
  Drawer,
  Card,
  Tooltip,
  Statistic,
  RadioGroup,
  RangePicker
} from 'ant-design-vue'
import {
  SyncOutlined,
  PlusOutlined,
  EditOutlined,
  CopyOutlined,
  DeleteOutlined,
  QuestionCircleOutlined,
  UnorderedListOutlined,
  ExclamationCircleOutlined,
  DownOutlined
} from '@ant-design/icons-vue'
import { requestSuccess, requestFailed } from '@/utils/feedback'
import { delSiteItem, getSiteList, editSiteInfo, delSiteBatch } from '@/api/logs'
import { useRouter } from 'vue-router'
import { todayDate, randomString } from '@/utils/common'
import { getAllServerList as getPushServerList } from '@/api/push'

export default defineComponent({
  name: 'Captcha',
  components: {
    SyncOutlined,
    PlusOutlined,
    EditOutlined,
    CopyOutlined,
    ExclamationCircleOutlined,
    UnorderedListOutlined,
    QuestionCircleOutlined,
    DownOutlined,
    DeleteOutlined,
    [Row.name]: Row,
    [Card.name]: Card,
    [Tooltip.name]: Tooltip,
    [RadioGroup.name]: RadioGroup,
    [RangePicker.name]: RangePicker,
    [Divider.name]: Divider,
    [Statistic.name]: Statistic,
    [Drawer.name]: Drawer,
    [Col.name]: Col
  },
  setup() {
    const formRef = ref()
    const router = useRouter()
    const state = reactive<any>({
      loading: true,
      drawerShow: false,
      submitLoading: false,
      today: todayDate(),
      dataList: [],
      allCaptcheData: [],
      optionsParams: [],
      selectedRowKeys: [],
      selectedKeysPage: {},
      allPush: [],
      secretShow: {},
      totalData: {},
      allLineRender: '',
      singleLineRender: '',
      ticketLineRender: '',
      dataTime: '',
      allLine: ref(),
      singleLine: ref(),
      ticketLine: ref(),
      activeKey: ref('1'),
      listQuery: {
        pageNo: 1,
        pageSize: 15,
        date_range: [],
        date_range_format: [],
        date_num: -1
      },
      listQuerySingle: {
        app_id: '',
        date_range: [],
        date_range_format: [],
        date_num: 0
      },
      pagination: {
        pageSizeOptions: ['15', '30', '50'],
        showSizeChanger: true,
        total: 1,
        showTotal: (total) => `共 ${total} 条数据`,
        pageSize: 15,
        current: 1
      },
      labelCol: {
        xs: { span: 24 },
        sm: { span: 3 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 20 }
      },
      columns: [
        {
          title: 'ID',
          dataIndex: '_id'
        },
        {
          title: '站点名',
          slots: { customRender: 'list_title' }
        },
        {
          title: '消息推送',
          dataIndex: 'notice_open',
          slots: { customRender: 'notice_open' }
        },
        {
          title: '推送配置',
          dataIndex: 'push_server_title'
        },
        {
          title: '状态',
          dataIndex: 'status',
          slots: { customRender: 'status' }
        },
        {
          title: '创建时间',
          dataIndex: 'create_time'
        },
        {
          title: '备注',
          dataIndex: 'desc'
        },
        {
          title: '操作',
          width: '280px',
          slots: { customRender: 'action' }
        }
      ]
    })
    onMounted(() => {
      getDataList()
      getServerDataList()
    })
    function getServerDataList() {
      getPushServerList({}).then((res) => {
        state.allPush = res
      })
    }
    function resetSecret() {
      FormState.server_secret = randomString(64)
    }

    const FormState = reactive<any>({
      title: '',
      save_day: '',
      status: '',
      server_secret: '',
      log_params: ''
    })
    watch(
      () => FormState.log_params,
      () => {
        let logParams = FormState.log_params.split('\n')
        for (let i = 0; i < logParams.length; i++) {
          let paramsItem = logParams[i].split('|')
          state.optionsParams[i] = { label: paramsItem[0], value: paramsItem[1] }
        }
      },
      {
        deep: true
      }
    )
    const FormRule = {
      title: [{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }],
      log_params: [{ required: true, message: '请输入日志参数', trigger: ['blur', 'change'] }],
      status: [{ required: true, message: '请选择验证场景', trigger: ['blur', 'change'] }],
      server_secret: [{ required: true, message: '请先获取密钥', trigger: ['blur', 'change'] }],
      save_day: [{ required: true, message: '请输入日志保留天数', trigger: ['blur', 'change'] }]
    }

    function handleTableChange(e) {
      state.loading = true
      state.pagination.pageSize = e.pageSize
      state.listQuery.pageSize = e.pageSize
      state.listQuery.pageNo = e.current
      state.pagination.current = e.current
      getDataList()
    }

    function reloadList() {
      state.loading = true
      state.listQuery.pageNo = 1
      state.pagination.current = 1
      getDataList()
    }

    function searchSubmit() {
      state.loading = true
      state.listQuery.pageNo = 1
      state.pagination.current = 1
      getDataList()
    }
    function log_site_edit(res) {
      for (let item in FormState) {
        FormState[item] = ''
      }
      for (let item in res) {
        FormState[item] = res[item]
      }
      state.drawerShow = true
    }
    function log_site_copy(res) {
      for (let item in FormState) {
        FormState[item] = ''
      }
      for (let item in res) {
        if (item != '_id' && item != 'server_secret') {
          if (item == 'title') {
            FormState[item] = res[item] + ' - 复制'
          } else {
            FormState[item] = res[item]
          }
        }
      }
      state.drawerShow = true
    }
    function log_site_add() {
      for (let item in FormState) {
        FormState[item] = ''
      }
      state.drawerShow = true
    }

    function getDataList() {
      getSiteList(state.listQuery).then((res) => {
        state.loading = false
        state.dataList = res
        for (let index = 0; index < res.data.length; index++) {
          const element = res.data[index]
          state.secretShow[element.app_id] = false
        }
        state.pagination.total = res.totalCount
      })
    }
    const addItem = () => {
      formRef.value
        .validate()
        .then(() => {
          state.submitLoading = true
          FormState.searchParamsOptions = JSON.stringify(state.optionsParams)
          editSiteInfo(toRaw(FormState))
            .then((res) => {
              if (res.code === 200) {
                requestSuccess(res)
                formRef.value.resetFields()
                state.loading = true
                state.drawerShow = false
                reloadList()
              } else {
                requestFailed(res)
              }
            })
            .finally(() => {
              state.submitLoading = false
            })
        })
        .catch(() => {
          return false
        })
    }
    function log_site_delete(data) {
      Modal.confirm({
        title: '确认删除?',
        content: '【' + data.title + '】',
        okType: 'danger',
        okText: '确认删除',
        onOk() {
          delSiteItem({ id: data._id }).then((res) => {
            if (res.code === 200) {
              state.loading = true
              getDataList()
              requestSuccess(res)
            } else {
              requestFailed(res)
            }
          })
        }
      })
    }
    function deleteSelect() {
      Modal.confirm({
        title: '确认批量删除所选内容?',
        okType: 'danger',
        okText: '确认删除',
        onOk() {
          delSiteBatch({ ids: state.selectedRowKeys })
            .then((res) => {
              if (res.code === 200) {
                state.loading = true
                getDataList()
                requestSuccess(res)
              } else {
                requestFailed(res)
              }
            })
            .finally(() => {
              state.selectedRowKeys = []
            })
        }
      })
    }
    const onSelectChange = (selectedRowKeys) => {
      state.selectedKeysPage[state.listQuery.pageNo] = selectedRowKeys
      let nowList: any[] = []
      for (const key in state.selectedKeysPage) {
        nowList = nowList.concat(state.selectedKeysPage[key])
      }
      const uniqueList = [...new Set(nowList)]
      state.selectedRowKeys = uniqueList
    }
    return {
      ...toRefs(state),
      handleTableChange,
      deleteSelect,
      onSelectChange,
      reloadList,
      searchSubmit,
      log_site_delete,
      formRef,
      log_site_add,
      resetSecret,
      FormState,
      log_site_edit,
      addItem,
      FormRule,
      log_site_copy,
      router,
      getDataList
    }
  }
})
</script>

<style scoped></style>
